// import com->alibaba->druid->DbType;
// import com->alibaba->druid->sql->SQLUtils;
// import com->alibaba->druid->sql->ast->*;
// import com->alibaba->druid->sql->ast->expr->*;
// import com->alibaba->druid->sql->dialect->mysql->ast->MySqlKey;
// import com->alibaba->druid->sql->dialect->mysql->ast->MySqlPrimaryKey;
// import com->alibaba->druid->sql->dialect->mysql->ast->MySqlUnique*;
// import com->alibaba->druid->sql->dialect->mysql->ast->statement->MySqlTableIndex;
// import com->alibaba->druid->sql->dialect->oracle->ast->stmt->OracleCreateSynonymStatement;
// import com->alibaba->druid->sql->parser->SQLParserUtils;
// import com->alibaba->druid->sql->semantic->SemanticException;
// import com->alibaba->druid->sql->visitor->SQLASTVisitor*;
// import com->alibaba->druid->util->FnvHash;
// import com->alibaba->druid->util->ListDG;
// import com->alibaba->druid->util->lang->Consumer;

// import java->util->*;
#pragma once

#include <string>
#include <list>

#include "../SQLExpr.h"
#include "../SQLExprImpl.h"
#include "../Object.h"
#include "../SQLName.h"
#include "../SQLReplaceable.h"
#include "../SQLStatementImpl.h"
#include "../SQLStatement.h"

#include "../../../DbType.h"

#include "SQLTableElement.h"
#include "SQLExprTableSource.h"
#include "SQLDDLStatement.h"
#include "SQLCreateStatement.h"

class SQLSelect;
class SQLColumnDefinition;
class SQLAssignItem;
class SQLPrimaryKey;
class SQLASTVisitor;
class SQLPartitionBy;
class SQLAlterTableItem;

class SQLCreateTableStatement : public SQLStatementImpl /*, public SQLDDLStatement, public SQLCreateStatement */
{
public:
  enum Type
  {
    GLOBAL_TEMPORARY,
    LOCAL_TEMPORARY,
    TEMPORARY,
    SHADOW
  };

public:
  BOOL_ptr ifNotExists;
  Type type;
  SQLExprTableSource_ptr tableSource;
  SQLTableElement_list_ptr tableElementList;

  // for postgresql
  SQLExprTableSource_ptr inherits;
  SQLSelect_ptr select;
  SQLExpr_ptr comment;
  SQLExprTableSource_ptr like;

  BOOL_ptr compress;
  BOOL_ptr logging;

  SQLName_ptr tablespace;
  SQLPartitionBy_ptr partitioning;
  SQLPartitionBy_ptr localPartitioning;
  SQLExpr_ptr storedAs;
  SQLExpr_ptr location;

  BOOL_ptr onCommitPreserveRows;
  BOOL_ptr onCommitDeleteRows;
  BOOL_ptr external;

  // for odps & hive
  SQLExternalRecordFormat_ptr rowFormat;
  SQLColumnDefinition_list_ptr partitionColumns;
  // ClusteringType* clusteringType;
  SQLSelectOrderByItem_list_ptr clusteredBy;
  SQLSelectOrderByItem_list_ptr sortedBy;
  int buckets;
  int shards;
  SQLAssignItem_list_ptr tableOptions;
  SQLAssignItem_list_ptr tblProperties;

  BOOL_ptr replace;
  BOOL_ptr ignore;
  BOOL_ptr single; // polardbx
  BOOL_ptr dimension;
  SQLExpr_ptr engine;
  std::shared_ptr<std::map<string_ptr, string_list_ptr>> attributes_;

  SQLCreateTableStatement();

  SQLCreateTableStatement(DbType_ptr dbType);
  virtual ~SQLCreateTableStatement(){};
  SHAREDOBJECT(SQLCreateTableStatement);

  void accept0(SQLASTVisitor_ptr v) override;

  void acceptChild(SQLASTVisitor_ptr v);

  SQLExpr_ptr getComment();

  void setComment(SQLExpr_ptr comment);

  SQLName_ptr getName();

  string_ptr getTableName();

  string_ptr getSchema();

  void setSchema(string_ptr name);

  void setName(SQLName_ptr name);

  void setName(string_ptr name);

  SQLExprTableSource_ptr getTableSource();

  void setTableSource(SQLExprTableSource_ptr tableSource);

  void setTableName(string_ptr tableName);

  Type getType();

  void setType(Type type);

  SQLTableElement_list_ptr getTableElementList();

  SQLColumnDefinition_ptr getColumn(string_ptr columnName);

  SQLColumnDefinition_list_ptr getColumnDefinitions();

  string_list_ptr getColumnNames(BOOL_ptr normalized);

  string_list_ptr getColumnComments();

  string_list_ptr getPrimaryKeyNames();

  void addColumn(string_ptr columnName, string_ptr dataType);

  void addColumn(SQLColumnDefinition_ptr column);

  BOOL_ptr isIfNotExists();

  void setIfNotExiists(BOOL_ptr ifNotExists);

  SQLExprTableSource_ptr getInherits();

  void setInherits(SQLExprTableSource_ptr inherits);

  SQLSelect_ptr getSelect();

  void setSelect(SQLSelect_ptr select);

  SQLExprTableSource_ptr getLike();

  void setLike(SQLName_ptr like);

  void setLike(SQLExprTableSource_ptr like);

  BOOL_ptr getCompress();

  void setCompress(BOOL_ptr compress);

  BOOL_ptr getLogging();

  void setLogging(BOOL_ptr logging);

  SQLName_ptr getTablespace();

  void setTablespace(SQLName_ptr x);

  SQLPartitionBy_ptr getPartitioning();

  SQLPartitionBy_ptr getLocalPartitioning();

  void setPartitioning(SQLPartitionBy_ptr partitioning);

  void setLocalPartitioning(SQLPartitionBy_ptr localPartitioning);

  SQLObject_list_ptr getChildren();

  // @SuppressWarnings("unchecked")
  void addBodyBeforeComment(string_list_ptr comments);

  // @SuppressWarnings("unchecked")
  string_list_ptr getBodyBeforeCommentsDirect();

  BOOL_ptr hasBodyBeforeComment();

  string_ptr computeName();

  SQLColumnDefinition_ptr findColumn(string_ptr columName);
  SQLColumnDefinition_ptr findColumn(long columName_hash);

  BOOL_ptr isPrimaryColumn(string_ptr columnName);

  BOOL_ptr isPrimaryColumn(long columnNameHash);

  BOOL_ptr isOnlyPrimaryKey(long columnNameHash);

  /**
   * only for show columns
   */
  BOOL_ptr isMUL(string_ptr columnName);

  /**
   * only for show columns
   */
  BOOL_ptr isUNI(string_ptr columnName);

  // MySqlUnique* findUnique(string_ptr  columnName) ;

  SQLTableElement_ptr findIndex(string_ptr columnName);

  // void forEachColumn(Consumer<SQLColumnDefinition*> columnConsumer) ;

  SQLPrimaryKey_ptr findPrimaryKey();

  // std::list<SQLForeignKeyConstraint*> findForeignKey() ;

  BOOL_ptr hashForeignKey();

  BOOL_ptr isReferenced(SQLName_ptr tableName);

  BOOL_ptr isReferenced(string_ptr tableName);

  // SQLAlterTableStatement* foreignKeyToAlterTable() ;

  static void sort(SQLStatement_list_ptr stmtList);

  void simplify();

  BOOL_ptr apply(SQLDropIndexStatement_ptr x);

  // BOOL_ptr apply(SQLCommentStatement* x) ;

  // BOOL_ptr apply(SQLAlterTableStatement* alter) ;

  BOOL_ptr alterApply(SQLAlterTableItem *item);

  // SQLAlterTableRenameColumn

  // BOOL_ptr apply(SQLAlterTableRenameColumn* item) ;

  BOOL_ptr renameColumn(string_ptr colummName, string_ptr newColumnName);

  // BOOL_ptr apply(SQLAlterTableRename* item) ;

  // BOOL_ptr apply(SQLAlterTableDropForeignKey* item) ;

  // BOOL_ptr apply(SQLAlterTableDropKey* item) ;

  // BOOL_ptr apply(SQLAlterTableDropConstraint* item) ;

  // BOOL_ptr apply(SQLAlterTableDropIndex* item) ;

  // BOOL_ptr apply(SQLAlterTableDropPrimaryKey* item) ;

  // BOOL_ptr apply(SQLAlterTableAddConstraint* item) ;

  // BOOL_ptr apply(SQLAlterTableDropColumnItem *item) ;

  // BOOL_ptr apply(SQLAlterTableAddIndex* item) ;

  // BOOL_ptr apply(SQLAlterTableAddColumn* item) ;

  int columnIndexOf(SQLName_ptr column);

  void cloneTo(SQLCreateTableStatement_ptr x);

  BOOL_ptr isReplace();

  void setReplace(BOOL_ptr replace);

  BOOL_ptr isIgnore();

  void setIgnore(BOOL_ptr ignore);

  BOOL_ptr isSingle();

  void setSingle(BOOL_ptr single);

  SQLExpr_ptr getStoredAs();

  void setStoredAs(SQLExpr_ptr x);

  // SQLCreateTableStatement *clone();
  virtual SQLObject_ptr clone();
  string_ptr toString();

  BOOL_ptr isOnCommitPreserveRows();

  void setOnCommitPreserveRows(BOOL_ptr onCommitPreserveRows);

  // for odps & hive
  BOOL_ptr isExternal();

  void setExternal(BOOL_ptr external);

  // ClusteringType* getClusteringType() ;

  // void setClusteringType(ClusteringType* clusteringType) ;

  SQLSelectOrderByItem_list_ptr getClusteredBy();

  void addClusteredByItem(SQLSelectOrderByItem_ptr item);

  SQLSelectOrderByItem_list_ptr getSortedBy();

  void addSortedByItem(SQLSelectOrderByItem_ptr item);

  int getBuckets();

  void setBuckets(int buckets);

  int getShards();

  void setShards(int shards);

  SQLColumnDefinition_list_ptr getPartitionColumns();

  void addPartitionColumn(SQLColumnDefinition_ptr column);

  SQLAssignItem_list_ptr getTableOptions();

  SQLAssignItem_list_ptr getTblProperties();

  void addTblProperty(string_ptr name, SQLExpr_ptr value);

  SQLExternalRecordFormat_ptr getRowFormat();

  void setRowFormat(SQLExternalRecordFormat_ptr x);

  BOOL_ptr isDimension();

  void setDimension(BOOL_ptr dimension);

  SQLExpr_ptr getLocation();

  void setLocation(SQLExpr_ptr x);

  void addOption(string_ptr name, SQLExpr_ptr value);

  SQLExpr_ptr getOption(string_ptr name);

  SQLExpr_ptr getTblProperty(string_ptr name);

  Object_ptr getOptionValue(string_ptr name);

  Object_ptr getTblPropertyValue(string_ptr name);

  Object_ptr getOptionOrTblPropertyValue(string_ptr name);

  string_ptr getCatalog();

  BOOL_ptr containsDuplicateColumnNames();

  BOOL_ptr containsDuplicateColumnNames(BOOL_ptr throwException);

  SQLExpr_ptr getEngine();

  void setEngine(SQLExpr_ptr x);

  // DDLObjectType* getDDLObjectType() ;
};
